// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import ComponentBase from "../../../general/Script/component/ComponentBase";
import { subGameMgr } from "../../../general/Script/mgr/SubGameMgr";
import { AssetsMgr, g_bundleName, resType } from "../../../general/Script/mgr/assetsManager";
import DataMgr from "../../../general/Script/mgr/dataManager";
import GameMgr from "../../../general/Script/mgr/gameManager";
import NativeMgr from "../../../general/Script/mgr/nativeManager";
import SoundMgr from "../../../general/Script/mgr/soundManager";
import BlockGMLogic from "./BlockGMLogic";
import BlockGMData from "./blockGMData";
import { GameType } from "./content";

import BlockTouch from "./prefab/blockTouch";




const { ccclass, property } = cc._decorator;

@ccclass
export default class BlockGmMgr extends ComponentBase {


    @property(cc.Prefab)
    blockPrefab: cc.Prefab = null;

    @property(cc.Prefab)
    combPrefab: cc.Prefab = null;

    @property(cc.Prefab)
    addScorePrefab: cc.Prefab = null;

    // @property([cc.Prefab])
    blockTouches: cc.Prefab[] = [];

    @property([cc.SpriteFrame])
    blockSp: cc.SpriteFrame[] = [];

    @property(cc.SpriteFrame)
    blockOverSp: cc.SpriteFrame = null;

    @property(cc.SpriteFrame)
    blockDiamondSp: cc.SpriteFrame = null;

    @property([cc.SpriteFrame])
    diamondsSp: cc.SpriteFrame[] = [];

    @property(cc.SpriteFrame)
    blockStoneSp: cc.SpriteFrame = null;

    // @property(cc.Prefab)
    overNode: cc.Prefab = null;

    // @property(cc.Prefab)
    settingNode: cc.Prefab = null;

    blockGame: cc.Node = null;
    blockNew: cc.Node = null;
    scoreNode: cc.Node = null;
    // blockEffect:cc.Node = null;
    blockGameEffectRow: cc.Node = null;
    blockGameEffectCol: cc.Node = null;
    scoreEffect: cc.Node = null;
    blockEffect: cc.Node = null;
    blockStar: cc.Node = null;
    blockStep: cc.Node = null;
    scoreLeft: cc.Node = null;

    highScore: cc.Node = null;

    data: BlockGMData = null;
    logic: BlockGMLogic = null;


    blockColor = 5;
    gameRow = 8;
    gameCol = 8;
    isGame_over = false;
    pos_touch_start: cc.Vec2 = null;
    touchNode: cc.Node = null;

    gameType: GameType = GameType.normal;

    sendMoveMsgPos: cc.Vec2 = null;
    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        super.onLoad();

        this.initGameEvent();

        DataMgr.Ins().setGameData('blockSp', this.blockSp);
        DataMgr.Ins().setGameData('blockOverSp', this.blockOverSp);
        DataMgr.Ins().setGameData('blockDiamondSp', this.blockDiamondSp);
        DataMgr.Ins().setGameData('diamondsSp', this.diamondsSp);
        DataMgr.Ins().setGameData('blockStoneSp', this.blockStoneSp);

        this.data = new BlockGMData(this.node, this);
        this.logic = new BlockGMLogic(this.node, this);




        //初始化游戏地图

        this.data.initMap();
        this.logic.initMap(this.data.getMap());

        this.setTouchEvent()


    }


    start() {
        this.blockTouches = [];



        for (let i = 0; i < 40; i++) {
            AssetsMgr.obj().loadRes(g_bundleName.gameBlock, 'blockBase/Prefab/blockTouch/' + i).then((res: cc.Prefab) => {
                this.blockTouches.push(res);
                if (this.blockTouches.length == 40) {
                    this.startGame();

                    AssetsMgr.obj().preLoadRes(resType.file, g_bundleName.gameBlock, 'blockBase/Prefab/blockOver').then((prefab: cc.Prefab) => {
                        this.overNode = prefab
                    })
                    AssetsMgr.obj().preLoadRes(resType.file, g_bundleName.gameBlock, 'blockBase/Prefab/game_setting').then((prefab: cc.Prefab) => {
                        this.settingNode = prefab
                    })

                }
            })
        }


    }


    startGame(reStart: boolean = false) {

        //游戏类型
        const gameType = DataMgr.Ins().getGameData('gameType')

        this.gameType = gameType || GameType.normal;
        console.log('gameType = ', this.gameType);
        for (let i = 0; i < this.blockNew.children.length; i++) {
            const node = this.blockNew.children[i];
            node.removeFromParent(true);
            node.destroy()
            i--;
        }

        switch (this.gameType) {
            case GameType.normal:
                this.newGame(reStart)
                break;
            case GameType.score:
                this.newGameScore(reStart)
                break;
            case GameType.step:
                this.newGameStep(reStart)
                break;
            case GameType.star:
                this.newGameStar(reStart)
                break;

        }
    }


    initGameEvent() {
        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'reBlockGame', this.reGameFunc.bind(this))
        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'newBlockGame', this.startGame.bind(this))

        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'game_addScore', this.gameAddScore.bind(this))

        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'game_addStep', this.gameAddStep.bind(this))

        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'game_addStar', this.gameAddStar.bind(this))
        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'nextLevel', this.nextLevel.bind(this))

        GameMgr.Ins().on(`${this.name}_${this.node.uuid}`, 'overGame', this.overGame.bind(this))
    }


    nextLevel() {
        // const info = DataMgr.Ins().getGameInfo()
        // DataMgr.Ins().setGameData('gameType', info.gameType);
        // DataMgr.Ins().setGameData('gameTarget', info.targets);
        // DataMgr.Ins().setGameData('gamemap', info.map);

        this.startGame(true)
    }


    onDestroy(): void {
        super.onDestroy();
        this.node.off(cc.Node.EventType.TOUCH_START, this.touchStart, this);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this.touchMove, this);
        this.node.off(cc.Node.EventType.TOUCH_END, this.touchEnd, this);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this.touchCancel, this);

        DataMgr.Ins().deleteGameData();
        // DataMgr.Ins().deleteGameData('blockOverSp');

        // DataMgr.Ins().deleteGameData('blockSp');

    }


    newGame(restart = false) {
        console.error('newGame');
        this.scoreLeft.active = false;
        this.blockStep.active = false;
        this.blockStar.active = false;

        this.scoreNode.active = true;
        this.highScore.active = true;



        //没有就开始新游戏

        const high = DataMgr.Ins().getLocalStorage('highScore') || 0;
        DataMgr.Ins().setGameData('highScore', Number(high));
        if (high) {
            const highScore = this.highScore.getChildByName('score');
            highScore.getComponent(cc.Label).string = high.toString();
            this.data.highScore = Number(high);
        }




        //查找是否有历史记录
        const hasLocal = this.data.initMapFromLocal();
        if (hasLocal && !restart) {
            this.isGame_over = false;
            this.logic.refreshMap(this.data.getMap());
            this.logic.updateScore(this.data.getScore());
            this.logic.createTouchBlock(this.data.touchArr, this.data.diamondArr);
        } else {
            this.isGame_over = false;
            this.data.initMap();
            this.logic.refreshMap(this.data.getMap());

            this.data.setScore(0);
            this.logic.updateScore(this.data.getScore());

            this.logic.gameStart(() => {
                this.newTouchBlock();
            });
        }
    }



    initTargetAndMap() {
        this.data.initGameTarget(DataMgr.Ins().getGameData('gameTarget'));

        const map = DataMgr.Ins().getGameData('gamemap');
        if (map) {
            this.data.setMap(map);
        } else {
            this.data.initMap();
        }

        this.isGame_over = false;

        this.logic.refreshMap(this.data.getMap());
    }

    newGameScore(restart: boolean = false) {
        console.error('newGame');
        this.scoreLeft.active = true;
        this.blockStep.active = false;
        this.blockStar.active = false;

        this.scoreNode.active = false;
        this.highScore.active = false;

        this.initTargetAndMap()

        const score = this.data.getLeftScore()
        this.logic.updateLeftScore(score);

        this.logic.gameStart(() => {
            this.newTouchBlock();
        });

    }

    newGameStep(restart: boolean = false) {
        console.error('newGame');
        this.scoreLeft.active = false;
        this.blockStep.active = true;
        this.blockStar.active = false;

        this.scoreNode.active = false;
        this.highScore.active = false;

        this.initTargetAndMap()

        const score = this.data.getLeftStep()
        this.logic.updateLeftStep(score);

        this.logic.gameStart(() => {
            this.newTouchBlock();
        });
    }

    newGameStar(restart: boolean = false) {
        console.error('newGame');
        this.scoreLeft.active = false;
        this.blockStep.active = false;
        this.blockStar.active = true;

        this.scoreNode.active = false;
        this.highScore.active = false;


        this.blockStar.getComponent(cc.Layout).enabled = false;

        this.initTargetAndMap()

        const score = this.data.getLeftStar()
        this.logic.updateLeftDiamond(score);

        this.logic.gameStart(() => {
            this.newTouchBlock();
        });
    }



    gameAddScore(data, clear) {
        if ([GameType.star, GameType.step].indexOf(this.gameType) > -1) {
            return;
        }
        console.log('gameAddScore:', data);
        if (this.gameType === GameType.normal) {
            this.data.addScore(data);
            this.logic.updateScore(this.data.getScore())

        } else {
            const over = this.data.reduceLeftScore(data);
            this.logic.updateLeftScore(this.data.getLeftScore());
            if (over && !this.isGame_over) {
                this.gameOver(true);
            }
        }
        if (clear) {
            this.data.wantAddScore = 0;
        }


    }

    gameAddStep(data) {
        if ([GameType.step].indexOf(this.gameType) === -1) {
            return;
        }
        console.log('gameAddStep:', data);
        const over = this.data.reduceLeftStep();
        this.logic.updateLeftStep(this.data.getLeftStep());

        if (over && !this.isGame_over) {
            this.gameOver(true);
        }
    }

    gameAddStar(data) {
        if ([GameType.star].indexOf(this.gameType) === -1) {
            return;
        }
        console.log('gameAddStar:', data);
        const over = this.data.reduceLeftStar(data);
        this.logic.updateLeftDiamond(this.data.getLeftStar());

        if (over && !this.isGame_over) {
            this.gameOver(true);
        }
    }

    newTouchBlock(isReGame = false) {

        if (isReGame) {
            for (let i = 0; i < this.blockNew.children.length; i++) {
                const node = this.blockNew.children[i];
                node.removeFromParent(true);
                node.destroy()
                i--;
            }
        }


        if (this.blockNew.children.length === 0) {
            const arr = this.data.newTouchBlock(isReGame);
            this.logic.createTouchBlock(arr, this.data.diamondArr);
        }

        const gameOver = this.logic.checkGameOver();
        if (gameOver) {
            this.data.delMapInfo();
            this.gameOver();
        } else {
            this.data.saveMap();
        }
    }

    reGameFunc() {
        console.log('reGame');
        this.isGame_over = false;
        this.newTouchBlock(true);
    }


    gameOver(win: boolean = false) {
        console.log('game over');
        //是否看广告  没看 直接结束

        this.isGame_over = true;

        DataMgr.Ins().setGameData('score', this.data.getScore());
        DataMgr.Ins().setGameData('win', win);
        this.node.runAction(cc.sequence(cc.delayTime(0.5), cc.callFunc(() => {
            if (this.overNode) {
                const overNode = cc.instantiate(this.overNode);
                this.node.addChild(overNode);
                overNode.zIndex = 100;
                overNode.scale = 0.1;
                overNode.runAction(cc.scaleTo(0.3, 1).easing(cc.easeIn(2)));
            } else {
                AssetsMgr.obj().preLoadRes(resType.file, g_bundleName.gameBlock, 'blockBase/Prefab/blockOver').then((prefab: cc.Prefab) => {
                    this.overNode = prefab
                    const overNode = cc.instantiate(this.overNode);
                    this.node.addChild(overNode);
                    overNode.zIndex = 100;
                    overNode.scale = 0.1;
                    overNode.runAction(cc.scaleTo(0.3, 1).easing(cc.easeIn(2)));
                })
            }

        })))



        // this.logic.gameOver(overTime);
    }

    setTouchEvent() {

        this.node.on(cc.Node.EventType.TOUCH_START, this.touchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.touchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.touchCancel, this);

    }

    touchStart(event: cc.Event.EventTouch) {
        if (this.isGame_over) {
            return;
        }
        const pos = event.getLocation();
        var posBlockNew = this.blockNew.convertToNodeSpaceAR(pos);
        this.pos_touch_start = pos


        for (let i in this.blockNew.children) {
            const child = this.blockNew.children[i];
            const rect = child.getBoundingBox();
            if (rect.contains(posBlockNew)) {
                console.log('touch block:', i);
                this.touchNode = child;
                this.touchNode.getComponent(BlockTouch).touch();
                SoundMgr.Ins().playEffect('block_touch', g_bundleName.gameBlock);

            }
        }

    }

    touchMove(event: cc.Event.EventTouch) {

        if (this.isGame_over) {
            return;
        }
        if (this.touchNode == null) {
            return;
        }
        const pos = event.getLocation();
        const offsetY = 100;
        // this.blockNew.setPosition(pos);
        const posNew = cc.v2(pos.x - this.pos_touch_start.x, pos.y - this.pos_touch_start.y);
        var pos_move = event.getDelta()
        this.pos_touch_start.x = this.pos_touch_start.x + pos_move.x
        this.pos_touch_start.y = this.pos_touch_start.y + pos_move.y

        this.touchNode.getComponent(BlockTouch).resetPos(posNew)


        if (!this.sendMoveMsgPos) {
            this.sendMoveMsgPos = pos;
        } else {
            if (Math.abs(pos.x - this.sendMoveMsgPos.x) > 15 || Math.abs(pos.y - this.sendMoveMsgPos.y) > 15) {
                this.sendMoveMsgPos = pos;
                this.logic.checkCanPut();;
            }
        }



    }


    touchEnd(event: cc.Event.EventTouch) {
        if (this.isGame_over) {
            return;
        }
        if (this.touchNode == null) {
            return;
        }

        if (this.logic.changeNodeArr.length > 0) {
            this.logic.putBlock();
            SoundMgr.Ins().playEffect('block_put', g_bundleName.gameBlock);

            this.logic.clearBlocks(() => {

            })


            this.touchNode.removeFromParent(true);
            this.touchNode.destroy();
            this.touchNode = null;
            this.newTouchBlock();

        } else {
            this.touchNode.getComponent(BlockTouch).back();
            this.touchNode = null;
        }


    }

    touchCancel(event: cc.Event.EventTouch) {
        if (this.isGame_over) {
            return;
        }

        // if(this.touchNode == null){
        //     return;
        // }
        // this.touchNode.getComponent(BlockTouch).back();
        // this.touchNode = null;
    }




    reGameCallBack(target, data) {

        this.startGame(true);
    }


    testBtnCallBack() {

        // this.data.combTimes = 3;
        // this.touchNode = this.blockNew.children[0];
        // const pos = this.blockGame.children[0].position;
        // this.logic.actionPos = cc.v2(pos.x,pos.y);

        // this.logic.addScoreAction(10,2)


        // this.isGame_over = true;

        // DataMgr.Ins().setGameData('score',123);

        // const overNode = cc.instantiate(this.overNode);
        // this.node.addChild(overNode);
        // overNode.zIndex = 100;
        // overNode.scale = 0.1;
        // overNode.runAction(cc.scaleTo(0.2,1).easing(cc.easeIn(2)));


        const touchNodeLength = []
        for (let i = 0; i < this.blockTouches.length; i++) {
            const block = cc.instantiate(this.blockTouches[i]);
            const touch = block.getComponent(BlockTouch);
            const length = touch.getActiveLength()
            touchNodeLength.push(length);
            console.log('touchNode:', touchNodeLength);
        }



    }


    backHomeCallBack(target, data) {
        this.overGame()
    }

    overGame() {

        NativeMgr.Ins().showFullAds();

        cc.director.loadScene("home");
        subGameMgr.exitSubGame();

    }


    settingCallBack(target, data) {
        console.log('setting CallBack')

        if (this.settingNode) {
            const node = cc.instantiate(this.settingNode);
            this.node.addChild(node);
            node.zIndex = 100;
            node.x = 0;
            node.y = 0;
        } else {
            AssetsMgr.obj().preLoadRes(resType.file, g_bundleName.gameBlock, 'blockBase/Prefab/game_setting').then((prefab: cc.Prefab) => {
                this.settingNode = prefab
                const node = cc.instantiate(this.settingNode);
                this.node.addChild(node);
                node.zIndex = 100;
                node.x = 0;
                node.y = 0;
            })
        }

    }

}
